package com.uinnova.product.eam.web.eam.mvc;

import com.binary.core.util.BinaryUtils;
import com.binary.framework.web.RemoteResult;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.uinnova.product.eam.comm.model.es.EamMultiModelHierarchy;
import com.uinnova.product.eam.comm.model.es.EamMultiModelType;
import com.uinnova.product.eam.service.IBmMultiModelHierarchySvc;
import com.uinnova.product.eam.web.eam.peer.IFlushPeer;
import com.uinnova.product.vmdb.comm.doc.annotation.ModDesc;
import com.uino.bean.cmdb.base.ESCIAttrDefInfo;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.ESCIRltInfo;
import com.uino.dao.cmdb.ESCIClassSvc;
import com.uino.dao.cmdb.ESCIRltSvc;
import com.uino.dao.cmdb.ESCISvc;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author lichong
 * @since 2022/5/12 14:00
 */
@Slf4j
@RestController
@RequestMapping("/flushData")
public class FlushController {

    @Autowired
    ESCIRltSvc esciRltSvc;

    @Autowired
    private ESCISvc esCiSvc;

    @Autowired
    private IBmMultiModelHierarchySvc modelHierarchySvc;

    @Autowired
    private ESCIClassSvc esClassSvc;

    @Autowired
    private IFlushPeer flushPeer;

    @PostMapping("flushRltSearchData")
    public String flushRltSearchData(){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.mustNot(QueryBuilders.existsQuery("targetCiSearchValues"));
        List<ESCIRltInfo> listByQuery = esciRltSvc.getListByQueryScroll(boolQueryBuilder);
        List<ESCIClassInfo> esciClassInfos = esClassSvc.getListByQueryScroll(QueryBuilders.matchAllQuery());
        HashMap<Long, ESCIClassInfo> tmpMap = Maps.newHashMap();
        for (ESCIClassInfo esciClassInfo : esciClassInfos) {
            tmpMap.put(esciClassInfo.getId(),esciClassInfo);
        }
        BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
        boolQueryBuilder1.must(QueryBuilders.termsQuery("classId",tmpMap.keySet()));
        List<ESCIInfo> listByQueryScroll = esCiSvc.getListByQueryScroll(boolQueryBuilder1);
        Map<Long, ESCIInfo> ciTmpMap = listByQueryScroll.stream().collect(Collectors.toMap(ESCIInfo::getId,o ->o));
        ArrayList<ESCIRltInfo> objects = Lists.newArrayList();
        for (ESCIRltInfo esciRltInfo : listByQuery) {
            if(esciRltInfo.getSourceCiId()==null||esciRltInfo.getTargetCiId()==null){
                continue;
            }
            Long sCiId = esciRltInfo.getSourceCiId();
            Long tCiId = esciRltInfo.getTargetCiId();
            ESCIInfo sourceCi = ciTmpMap.get(sCiId);
            Assert.notNull(sourceCi, "源ci不存在");
            ESCIClassInfo sourceCiClass = tmpMap.get(sourceCi.getClassId());
            List<String> sourceSearchFiles = getSearchFiles(sourceCiClass);
            String s = sourceCiClass.getClassName()+"_"+ getSearchFileValues(sourceCi,sourceSearchFiles);
            ESCIInfo targetCi = ciTmpMap.get(tCiId);
            Assert.notNull(targetCi, "目标ci不存在");
            ESCIClassInfo targetCiClass = tmpMap.get(targetCi.getClassId());
            List<String> targetSearchFiles = getSearchFiles(targetCiClass);
            String s1 = targetCiClass.getClassName()+"_"+ getSearchFileValues(targetCi,targetSearchFiles);
            esciRltInfo.setSourceCiSearchValues(s);
            esciRltInfo.setTargetCiSearchValues(s1);
            objects.add(esciRltInfo);
        }

        int batchSize=3000;
        if(objects.size()<batchSize){
            esciRltSvc.saveOrUpdateBatch(objects);
        }else {
            for (int i =1;i<1000;i++){
                esciRltSvc.saveOrUpdateBatch(objects.subList((i-1)*batchSize,
                        Math.min((i - 1) * batchSize + batchSize, objects.size())));
            }
        }
        return "success";
    }

    private List<String> getSearchFiles(ESCIClassInfo sourceCiClass) {
        ArrayList<String> sourceSearchFiles = Lists.newArrayList();
        for (ESCIAttrDefInfo attrDef : sourceCiClass.getAttrDefs()) {
            if(attrDef.getIsCiDisp()==1||attrDef.getIsMajor()==1){
                sourceSearchFiles.add(attrDef.getProStdName()) ;
            }
        }
        return sourceSearchFiles;
    }

    private String getSearchFileValues(ESCIInfo esciInfo,List<String> files) {
        List<String> collect = files.stream().map(s ->
                        esciInfo.getAttrs().get(s) == null ? "" : esciInfo.getAttrs().get(s).toString())
                .collect(Collectors.toList());
        return StringUtils.join(collect, "_");
    }

    @GetMapping ("/crushModelType")
    public String crushModelType() {
        //刷新模型树类型  数据接口
        List<EamMultiModelHierarchy> modelHierarchies = modelHierarchySvc.queryList(null, 1);
        if(!BinaryUtils.isEmpty(modelHierarchies)){
            for (EamMultiModelHierarchy modelHierarchy : modelHierarchies) {
                Integer modelType = modelHierarchy.getModelType();
                if(BinaryUtils.isEmpty(modelType)){
                    EamMultiModelType type = modelHierarchy.getType();
                    if("数据建模".equals(type.getName())){
                        modelHierarchy.setModelType(1);
                    }else{
                        modelHierarchy.setModelType(2);
                    }
                }
            }
            modelHierarchySvc.saveOrUpdateBatch(modelHierarchies);
        }
        return "success";
    }

    @PostMapping("/category/flushNewDir")
    @ModDesc(desc = "刷数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushNewDir() {
        flushPeer.flushNewDir();
        return new RemoteResult(1);
    }

    @PostMapping("/category/flushSystemDir")
    @ModDesc(desc = "刷系统文件夹数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushSystemDir() {
        flushPeer.flushSystemDir();
        return new RemoteResult(1);
    }

    @PostMapping("/category/flushGeneralDir")
    @ModDesc(desc = "刷公共文件夹数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushGeneralDir() {
        flushPeer.flushGeneralDir();
        return new RemoteResult(1);
    }

    @PostMapping("/category/flushPlan")
    @ModDesc(desc = "刷方案所属文件夹数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushPlan() {
        flushPeer.flushPlan();
        return new RemoteResult(1);
    }

    @PostMapping("/category/refreshCategoryDirLvl")
    @ModDesc(desc = "刷系统文件夹数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult refreshCategoryDirLvl() {
        flushPeer.refreshCategoryDirLvl();
        return new RemoteResult(1);
    }

    @PostMapping("/newMenu/flushAll")
    @ModDesc(desc = "新版菜单存量数据处理", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushAll() {
        flushPeer.flushNewDir();
        flushPeer.flushGeneralDir();
        flushPeer.flushPlan();
        return new RemoteResult(1);
    }

    @GetMapping("/category/permission/fix")
    @ModDesc(desc = "修复新版目录后创建目录时未同步创建目录权限", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult designCategoryPermissionFix() {
        Integer count = flushPeer.designCategoryPermissionFix();
        return new RemoteResult(count);
    }

    @GetMapping("/model/permission/flush")
    @ModDesc(desc = "刷空的模型权限数据", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushModelPermission() {
        Map<String, Integer> map = flushPeer.flushModelPermission();
        return new RemoteResult(map);
    }

    @GetMapping("/model/version/tagDir")
    @ModDesc(desc = "模型根目录及L0层级目录的parentId", pDesc = "", rDesc = "", rType = RemoteResult.class)
    public RemoteResult flushModelVersionTagDir() {
        Map<String, Integer> result = flushPeer.flushModelVersionTagDir();
        return new RemoteResult(result);
    }
}
